String.prototype.repeat = function( num )
{
    return new Array( num + 1 ).join( this );
}

function Request(baseUrl, query) {
    this.baseUrl = baseUrl;
    this.query = null;

    if ( query ) {
        this.query = query;
    }
}

if ( Object.defineProperty ) {
    Object.defineProperty(Request.prototype, 'url', {
        get: function() {
            return Request.makeUrl(this.baseUrl, this.query);
        }
    });
}

Request.prototype.getUrl = function() {
    return Request.makeUrl(this.baseUrl, this.query);
}

Request.prototype.getJSON = function(callback, error) {
    getJSON(this.getUrl(), callback, error);
}

Request.prototype.postJSON = function(data, callback, error) {
    postJSON(this.getUrl(), data, callback, error);
}

Request.makeUrl = function(baseUrl, query) {
    if ( !query ) {
        return baseUrl;
    }

    var queryString = Request.makeQueryString(query);
    if ( queryString.length == 0 ) {
        return baseUrl;
    }

    return baseUrl + '?' + queryString;
}

Request.extractBaseUrl = function(href) {
    var queryPos = href.indexOf('?');
    if ( queryPos == -1 ) {
        return href;
    }

    return href.slice(0, queryPos);
}

Request.makeQueryString = function(parameters) {
    parameterList = [];
    for ( var key in parameters ) {
        var value = parameters[key];

        parameterList.push(key + '=' + value);
    }

    return parameterList.join('&');
}

Request.parseQueryString = function(queryString) {
    queryString = queryString.substring(1);
    if ( queryString == null || queryString == '' ) {
        return {};
    }

    var parameterList = queryString.split('&');
    var parameters = {};
    for ( parameterIndex in parameterList ) {
        var parameter = parameterList[parameterIndex];

        var keyValue = parameter.split('=');
        var key = keyValue[0];
        var value = keyValue[1];

        parameters[key] = value;
    }

    return parameters;
}

function Response() {
}

Response.prototype.redirectTo = function(request) {
    location.href = request.getUrl();
}

var Application = {
    showPage: function(page) {
        var queryString = window.location.search;
        var baseUrl = Request.extractBaseUrl(location.href);
        var query = Request.parseQueryString(queryString);
        var request = new Request(baseUrl, query);
        var response = new Response();

        page.request = request;
        page.response = response;

        if ( 'onInitialize' in page ) {
            page.onInitialize();
        }
        if ( 'onShow' in page ) {
            page.onShow();
        }
    }
};

function postJSON(url, data, callback, error) {
    $.ajax({
        url: url,
        type: 'post',
        contentType: 'application/json',
        data: JSON.stringify(data),
        dataType: 'json',
        success: function(data) {
            callback(data);
        },
        error: function(req, message, e) {
            console.log(message);
            console.log(e);

            if ( error ) {
                error(req, message, e);
            }
        }
    });
}

function getJSON(url, callback, error) {
    $.ajax({
        url: url,
        type: 'get',
        contentType: 'application/json',
        dataType: 'json',
        success: function(data) {
            callback(data);
        },
        error: function(req, message, e) {
            console.log(message);
            console.log(e);

            if ( error ) {
                error(req, message, e);
            }
        }
    });
}

function toJSON(object) {
    return JSON.stringify(object);
}

function fromJSON(data) {
    if ( !data ) {
        return undefined;
    }

    return $.parseJSON(data);
}

function redirectTo(url) {
    window.location.href = url;
}

function disableAll(e) {
    e.preventDefault();
    e.stopPropagation();
}

function formatDate(date) {
    var dateTemplate = _.template(
        '<%=d.getFullYear()%>-<%=paddingZero(d.getMonth() + 1, 2)%>-<%=paddingZero(d.getDate(), 2)%>');

    return dateTemplate({
        d: date
    });
}

function paddingZero(number, width) {
    var numberString = String(number);
    if ( numberString.length < width ) {
        numberString = '0'.repeat(width - numberString.length) + numberString;
    }

    return numberString;
}

function getDateOfDatePicker(widget) {
    var $widget = widget;
    if ( typeof(widget) == 'string' ) {
        $widget = $(widget);
    }

    var dateString = $widget.val();
    return fromDateString(dateString);
}

function fromDateString(dateString) {
    var year = Number(dateString.slice(0, 4));
    var month = Number(dateString.slice(5, 7)) - 1;
    var date = Number(dateString.slice(8, 10));
    var hour = Number(dateString.slice(11, 13));
    var minute = Number(dateString.slice(14, 16));

    return new Date(year, month, date, hour, minute);
}
